package frsf.cidisi.exercise.modelo.search;

import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import faiaMod.SearchMod;
import frsf.cidisi.exercise.modelo.search.actions.Avanzar;
import frsf.cidisi.exercise.modelo.search.actions.GirarDer;
import frsf.cidisi.exercise.modelo.search.actions.GirarIzq;
import frsf.cidisi.exercise.modelo.search.actions.LevantarLlave;
import frsf.cidisi.faia.agent.Action;
import frsf.cidisi.faia.agent.Perception;
import frsf.cidisi.faia.agent.search.Problem;
import frsf.cidisi.faia.agent.search.SearchAction;
import frsf.cidisi.faia.agent.search.SearchBasedAgent;
import frsf.cidisi.faia.solver.search.AStarSearch;
import frsf.cidisi.faia.solver.search.DepthFirstSearch;
import frsf.cidisi.faia.solver.search.IEstimatedCostFunction;
import frsf.cidisi.faia.solver.search.IStepCostFunction;
import frsf.cidisi.faia.solver.search.NTree;
import frsf.cidisi.faia.solver.search.Search;
import frsf.cidisi.faia.solver.search.UniformCostSearch;

public class Agente extends SearchBasedAgent {

    public Agente() {
    	
        // The Agent Goal
        AgenteMeta agGoal = new AgenteMeta();

        // The Agent State
        AgenteEstado agState = new AgenteEstado();
        this.setAgentState(agState);

        // Create the operators
        Vector<SearchAction> operators = new Vector<SearchAction>();
        operators.addElement(new GirarDer());	
        operators.addElement(new GirarIzq());	
        operators.addElement(new Avanzar());	
        operators.addElement(new LevantarLlave());

        // Create the Problem which the agent will resolve
        Problem problem = new Problem(agGoal, agState, operators);
        this.setProblem(problem);
    }

    /**
     * This method is executed by the simulator to ask the agent for an action.
     */
    @Override
    public Action selectAction() {

        // Create the search strategy
        IStepCostFunction cost = new CostFunction();
        IEstimatedCostFunction heuristic = new Heuristic();
        AStarSearch strategy = new AStarSearch(cost, heuristic);          

        // Create a Search object with the strategy
        Search searchSolver = new Search(strategy);

        /* Generate an XML file with the search tree. It can also be generated
         * in other formats like PDF with PDF_TREE */
        //searchSolver.setVisibleTree(Search.GRAPHVIZ_TREE);
        searchSolver.setVisibleTree(Search.EFAIA_TREE);

        // Set the Search searchSolver.
        this.setSolver(searchSolver);

        // Ask the solver for the best action
        Action selectedAction = null;
        try {
            selectedAction =
                    this.getSolver().solve(new Object[]{this.getProblem()});
        } catch (Exception ex) {
            Logger.getLogger(Agente.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Return the selected action
        //return selectedAction;
        return null;

    }

    /**
     * This method is executed by the simulator to give the agent a perception.
     * Then it updates its state.
     * @param p
     */
    @Override
    public void see(Perception p) {
        this.getAgentState().updateState(p);
    }
    
    public Vector<NTree> selectActionMod() {

        // Create the search strategy
        IStepCostFunction cost = new CostFunction();
        IEstimatedCostFunction heuristic = new Heuristic(); 
        AStarSearch strategy = new AStarSearch(cost, heuristic);          

        // Create a Search object with the strategy
        SearchMod searchSolver = new SearchMod(strategy);

        /* Generate an XML file with the search tree. It can also be generated
         * in other formats like PDF with PDF_TREE */
        //searchSolver.setVisibleTree(Search.GRAPHVIZ_TREE);
        searchSolver.setVisibleTree(Search.EFAIA_TREE);

        // Set the Search searchSolver.
        this.setSolver(searchSolver);

        // Ask the solver for the best action
        Action selectedAction = null;
        try {
            selectedAction =
                    this.getSolver().solve(new Object[]{this.getProblem()});
        } catch (Exception ex) {
            Logger.getLogger(Agente.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.getSolver().showSolution();
        Vector<NTree> camino = searchSolver.solveMod(new Object[]{this.getProblem()});
        
        // Return the selected actions
        return camino;

    }
    
    //TODO HACER PUNTO 2
    public Vector<NTree> selectActionMod2() {

    	// Create the search strategy
        IStepCostFunction cost = new UniformCostFunction();
        UniformCostSearch strategy = new UniformCostSearch(cost);          

        // Create a Search object with the strategy
        SearchMod searchSolver = new SearchMod(strategy);

        /* Generate an XML file with the search tree. It can also be generated
         * in other formats like PDF with PDF_TREE */
        searchSolver.setVisibleTree(Search.EFAIA_TREE);

        // Set the Search searchSolver.
        this.setSolver(searchSolver);

        // Ask the solver for the best action
        Action selectedAction = null;
        try {
            selectedAction =
                    this.getSolver().solve(new Object[]{this.getProblem()});
        } catch (Exception ex) {
            Logger.getLogger(Agente.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Return the selected action
        searchSolver.showSolution();
        Vector<NTree> camino = searchSolver.solveMod(new Object[]{this.getProblem()});
        return camino;

    }
    
    /* Problema 3 - Busqueda no informada */
    public Vector<NTree> selectActionMod3() {
    	// Create the search strategy
        DepthFirstSearch strategy = new DepthFirstSearch();          

        // Create a Search object with the strategy
        SearchMod searchSolver = new SearchMod(strategy);

        /* Generate an XML file with the search tree. It can also be generated
         * in other formats like PDF with PDF_TREE */
        searchSolver.setVisibleTree(Search.EFAIA_TREE);

        // Set the Search searchSolver.
        this.setSolver(searchSolver);

        // Ask the solver for the best action
        Action selectedAction = null;
        try {
            selectedAction =
                    this.getSolver().solve(new Object[]{this.getProblem()});
        } catch (Exception ex) {
            Logger.getLogger(Agente.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Return the selected action
        searchSolver.showSolution();
        Vector<NTree> camino = searchSolver.solveMod(new Object[]{this.getProblem()});
        return camino;
    }
}
